package org.mybatis.generator.plugins;

import java.util.List;
import java.util.Set;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.utils.JavaMapperGeneratorHelper;
import org.mybatis.generator.utils.XMLMapperGeneratorHelper;

/**
 * <b><code>SelectExistsPlugin</code></b>
 * <p/>
 * Description: 查询记录是否存在
 * <p/>
 * <b>Creation Time:</b> 2020/06/08.
 */
public class SelectExistsPlugin extends PluginAdapter {

	private final static String SELECT_EXISTS = "selectExistsByPrimaryKey";

	@Override
	public boolean validate(List<String> warnings) {
		return true;
	}

	@Override
	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
			clientSelectCountExistsMethodGenerated(interfaze, introspectedTable, context);
		}
		return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
	}

	@Override
	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
			sqlMapSelectCountExistsElementGenerated(document, introspectedTable, context);
		}
		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	private void sqlMapSelectCountExistsElementGenerated(Document document, IntrospectedTable introspectedTable,
			Context context) {
		XmlElement baseElement = XMLMapperGeneratorHelper.baseElementGenerator(XMLMapperGeneratorHelper.SELECT,
				SELECT_EXISTS, introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType().toString(),
				XMLMapperGeneratorHelper.RESULT_TYPE, "java.lang.Integer");

		StringBuilder sbr = new StringBuilder();
		sbr.append("select case when ");
		List<IntrospectedColumn> columns = introspectedTable.getPrimaryKeyColumns();
		if (columns.size() == 1) {
			sbr.append(String.format("count(%s) ", columns.get(0).getActualColumnName()));
		} else {
			sbr.append("count(1) ");
		}
		sbr.append(" > 0 then 1 else 0 end as result from ");
		sbr.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());

		baseElement.addElement(new TextElement(sbr.toString()));
		sbr.setLength(0);
		boolean and = false;
		for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) {
			if (and) {
				sbr.append("  and ");
			} else {
				sbr.append("where ");
				and = true;
			}

			sbr.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
			sbr.append(" = ");
			sbr.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn));
		}

		baseElement.addElement(new TextElement(sbr.toString()));
		document.getRootElement().addElement(baseElement);
	}

	private void clientSelectCountExistsMethodGenerated(Interface interfaze, IntrospectedTable introspectedTable,
			Context context) {
		Set<FullyQualifiedJavaType> importedTypes = JavaMapperGeneratorHelper
				.importedBaseTypesGenerator(introspectedTable);
		FullyQualifiedJavaType paramType = introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType();
		Method selectExistsMethod = JavaMapperGeneratorHelper.methodGenerator(SELECT_EXISTS, JavaVisibility.DEFAULT,
				FullyQualifiedJavaType.getIntInstance(),
				new Parameter(new FullyQualifiedJavaType(paramType.getFullyQualifiedName()),
						introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty()));

		context.getCommentGenerator().addGeneralMethodComment(selectExistsMethod, introspectedTable);
		interfaze.addImportedTypes(importedTypes);
		interfaze.addMethod(selectExistsMethod);
	}
}
